﻿#include "testplanbuilder.h"
#include "model/datamanager.h"
#include "common/calcutils.h"
#include <QtDebug>

TestPlanBuilder::TestPlanBuilder()
{
}
TestPlanBuilder::~TestPlanBuilder()
{
}

/**
 * @brief makeAlignedCurve 把原始曲线 curvePtr 重采样为“与 gridHz 一致”的曲线对象
 * @param src
 * @param gridHz
 * @return 返回的新曲线具有：xs = gridHz，ys = 重采样后的值；xScale/yScale 置 Linear（后续不再二次插值）
 * src 曲线“所有数据一样”（通常指所有 y 值相同，或所有点完全重合），对齐后的结果是一条常数曲线。
 * src 只有一个数据点，对齐后的结果同样是一条常数曲线。返回曲线 xs_Hz = gridHz，ys 全部等于这一个点的 y 值。
 */
Exec::CurvePtr TestPlanBuilder::makeAlignedCurve(const Exec::CurvePtr &src, const AxisScale xScale, const AxisScale yScale, const QVector<double> &gridHz)
{
    if (!src)
        return Exec::CurvePtr();
    const int n = src->xs_Hz.size();
    if (gridHz.isEmpty() || n <= 0 || src->ys.size() != n) {
        qWarning() << "src or gridHz  invalid";
        return Exec::CurvePtr();
    }

    // log 轴约束检查
    if (xScale == AxisScale::Logarithmic) {
        for (double x : src->xs_Hz)
            if (x <= 0)
                return Exec::CurvePtr();
        for (double gx : gridHz)
            if (gx <= 0)
                return Exec::CurvePtr();
    }
    if (src->yScale == AxisScale::Logarithmic) {
        for (double y : src->ys)
            if (y <= 0)
                return Exec::CurvePtr();
    }

    // 情况 单点或常数曲线 -> 快速返回“常数对齐曲线”
    auto isAllSameY = [&]() {
        const double y0 = src->ys.front();
        for (double y : src->ys) {
            if (!qFuzzyCompare(1.0 + y, 1.0 + y0))
                return false;
        }
        return true;
    };
    if (n == 1 || isAllSameY()) {
        QSharedPointer<Exec::Curve> aligned = QSharedPointer<Exec::Curve>::create();
        aligned->xScale = xScale; // 对齐后不再需要按比例插值
        aligned->yScale = yScale;
        aligned->sourceUnit = src->sourceUnit;
        aligned->targetUnit = src->targetUnit;
        aligned->xs_Hz = gridHz;
        aligned->ys.resize(gridHz.size());
        std::fill(aligned->ys.begin(), aligned->ys.end(), src->ys.front());
        return Exec::CurvePtr(aligned);
    }

    // 用 CalcUtils::resample 计算重采样后的 ys
    bool ok = false;
    QVector<double> alignedYs = CalcUtils::resample(src->xs_Hz, src->ys, gridHz, xScale, yScale, &ok);
    if (!ok) {
        // 失败时返回空，调用方可选择忽略或记录
        return Exec::CurvePtr();
    }

    // 组装新的只读曲线对象（xs 为 grid）
    QSharedPointer<Exec::Curve> writable = QSharedPointer<Exec::Curve>::create();
    writable->xScale = xScale;
    writable->yScale = yScale;
    writable->sourceUnit = src->sourceUnit;
    writable->targetUnit = src->targetUnit;
    writable->xs_Hz = gridHz; // 对齐网格
    writable->ys = std::move(alignedYs);
    return Exec::CurvePtr(writable);
}

// 构建只读快照：先用“可写”对象组装，最后“冻结”为 const 指针返回
Exec::TestPlanPtr TestPlanBuilder::build(const TestTemplate &tpl)
{
    // 作用域缓存清空
    hwCache_.clear();
    curveCache_.clear();
    calCache_.clear();

    // 可写计划指针（注意：不是 const）
    QSharedPointer<Exec::TestPlan> planWritable = QSharedPointer<Exec::TestPlan>::create();

    // 填充计划元数据（从 TestTemplate 拷贝）
    planWritable->id = tpl.id;
    planWritable->name = tpl.name;
    planWritable->stage = tpl.stage;       //测试阶段： cal /test /level
    planWritable->flowKind = tpl.flowKind; // 流程类型（Radiated/Conducted）
    planWritable->levelMode = tpl.levelMode;
    planWritable->powerMeasurement = tpl.powerMeasurement;
    planWritable->immunityUnit = tpl.immunityLevelUnit;
    planWritable->impedance_Ohm = tpl.impedance;
    planWritable->antennaFactor = tpl.antennaFactor;
    planWritable->cs_offset = tpl.offset;
    planWritable->cs_offsetCheck = tpl.offsetCheck;

    // 模板级校准表：如果所有子区间共用一张校准表
    Exec::CalTablePtr planLevelCalTable;
    if (tpl.calibrationDataID > 0) {
        planLevelCalTable = resolveCalTable(tpl.calibrationDataID);
    }
    QVector<double> calFreqs;
    calFreqs.clear();
    int commonHwType = -1;
    QVector<Exec::Subrange> subranges;
    subranges.reserve(tpl.subBands.size());

    double limitOffset = 0;
    //cs测试，闭环法，添加功率补偿
    if (tpl.flowKind == HardwareTemplateType::CS && tpl.stage == TestProcessStage::Testing
        && tpl.levelMode == LevelModeType::Sensor && tpl.offsetCheck)
        limitOffset = tpl.offset;

    for (int si = 0; si < tpl.subBands.size(); ++si) {
        const TestSubBandPtr &sbPtr = tpl.subBands.at(si);
        if (!sbPtr)
            continue;
        const TestSubBand &sb = *sbPtr;

        //展开频点网格（Hz）
        QVector<FreqTableConfig> freqTableRows;
        if (sb.freqTableID > 0) {
            // 获取频表
            const QList<FreqTableConfig> list = DataManager::instance()->getFreqTable(sb.freqTableID);
            freqTableRows = QVector<FreqTableConfig>::fromList(list);
        }
        QVector<double> freqPointsHz = expandFreqs(sb, freqTableRows.isEmpty() ? nullptr : &freqTableRows);
        if (freqPointsHz.isEmpty()) {
            qWarning() << "Subrange" << si << "has no frequency points, skipped.";
            continue;
        }
        calFreqs.append(freqPointsHz);
        // 解析硬件模板（只读；包含原始曲线）
        Exec::HardwarePtr hwResolved;
        if (sb.hardwareTemplateID > 0) {
            hwResolved = resolveHardware(sb.hardwareTemplateID);
            if (!hwResolved) {
                qWarning() << "resolveHardware failed, subrange" << si << "hwId=" << sb.hardwareTemplateID;
                continue;
            }
            // 校验硬件类型一致性
            int thisType = static_cast<int>(hwResolved->type);
            if (commonHwType == -1)
                commonHwType = thisType;
            else if (thisType != commonHwType) {
                qWarning() << "Hardware template type mismatch between subranges:"
                           << "expected=" << commonHwType << "actual=" << thisType << "on subrange" << si;
                return Exec::TestPlanPtr(); // 直接失败，返回空（也可抛异常/返回特定错误）
            }
            // 校验子区间频点是否在硬件频段内；超出可告警或裁剪
            if (!hwResolved->fmin_Hz && !hwResolved->fmax_Hz) {
                // 没设置范围时跳过检查
            } else {
                double minF = hwResolved->fmin_Hz;
                double maxF = hwResolved->fmax_Hz;
                if (minF > 0 && maxF > minF) {
                    if (freqPointsHz.front() < minF || freqPointsHz.back() > maxF) {
                        qWarning() << "Subrange" << si << "freq points out of hardware range:"
                                   << "grid(" << freqPointsHz.front() << "~" << freqPointsHz.back()
                                   << "), hw(" << minF << "~" << maxF << ")";
                        return Exec::TestPlanPtr();
                    }
                }
            }
        } else {
            // 未绑定硬件模板：允许构建但运行期会话创建会失败
            qWarning() << "Subrange" << si << "has no hardwareTemplateID.";
            return Exec::TestPlanPtr();
        }

        //  构建子区间级限值曲线
        Exec::CurvePtr limitCurve;
        if (sb.immunityLevelType == ImmunityLevelType::Fixed)
            limitCurve = buildCurveFromLimit(LimitLineList(), limitOffset, sb.immunityLevelValue, true);
        else if (sb.immunityLevelType == ImmunityLevelType::Table && sb.immunityLevelTableID > 0) {
            const LimitLineList lim = DataManager::instance()->getLimitLineTable(sb.immunityLevelTableID);
            limitCurve = buildCurveFromLimit(lim, limitOffset);
        }
        // 组装子区间基础字段
        Exec::Subrange sub;
        sub.id = sb.id;
        sub.spanFmin_Hz = sb.startFreq;
        sub.spanFmax_Hz = sb.stopFreq;
        sub.dwell_ms = sb.dwellTime;
        sub.modulation = sb.generatorModulation;
        sub.plumWidth = sb.plumWidth;
        sub.plumPeriod = sb.plumPeriod;
        sub.upperTol_dB = sb.upperTolerance;
        sub.lowerTol_dB = sb.lowerTolerance;
        sub.levelSrc = sb.immunityLevelType;
        sub.fixedImmunityLevel = sb.immunityLevelValue;
        sub.hw = hwResolved;                         // 只读硬件
        sub.freqPoints_Hz = std::move(freqPointsHz); // 统一网格
        sub.limitCurve = limitCurve;                 // 原始限值曲线（暂时）

        // 校准表（模板级共用；如有子区间级的，改这里）
        sub.cal = planLevelCalTable;

        if (sub.limitCurve) {
            sub.limitCurve = makeAlignedCurve(limitCurve, sb.stepMode, AxisScale::Linear, sub.freqPoints_Hz);
        }

        // 硬件级曲线对齐（保存在 Subrange；避免直接改 Exec::Hardware）
        if (sub.hw) {
            if (sub.hw->ampCouplerFwd)
                sub.ampCouplerFwdAligned = makeAlignedCurve(sub.hw->ampCouplerFwd, sb.stepMode, AxisScale::Linear, sub.freqPoints_Hz);
            if (sub.hw->ampCouplerRev)
                sub.ampCouplerRevAligned = makeAlignedCurve(sub.hw->ampCouplerRev, sb.stepMode, AxisScale::Linear, sub.freqPoints_Hz);
            if (sub.hw->antHFactors)
                sub.antHFactorsAligned = makeAlignedCurve(sub.hw->antHFactors, sb.stepMode, AxisScale::Linear, sub.freqPoints_Hz);
            if (sub.hw->antVFactors)
                sub.antVFactorsAligned = makeAlignedCurve(sub.hw->antVFactors, sb.stepMode, AxisScale::Linear, sub.freqPoints_Hz);
            if (sub.hw->probeFactors)
                sub.probeFactorsAligned = makeAlignedCurve(sub.hw->probeFactors, sb.stepMode, AxisScale::Linear, sub.freqPoints_Hz);

            if (sub.hw->probeCorr)
                sub.probeCorrAligned = makeAlignedCurve(sub.hw->probeCorr, sb.stepMode, AxisScale::Linear, sub.freqPoints_Hz);

            if (sub.hw->con_gen2Amp)
                sub.con_gen2AmpAligned = makeAlignedCurve(sub.hw->con_gen2Amp, sb.stepMode, AxisScale::Linear, sub.freqPoints_Hz);
            if (sub.hw->con_Fwd2Pm)
                sub.con_Fwd2PmAligned = makeAlignedCurve(sub.hw->con_Fwd2Pm, sb.stepMode, AxisScale::Linear, sub.freqPoints_Hz);
            if (sub.hw->con_Rev2Pm)
                sub.con_Rev2PmAligned = makeAlignedCurve(sub.hw->con_Rev2Pm, sb.stepMode, AxisScale::Linear, sub.freqPoints_Hz);
            if (sub.hw->con_amp2Tran)
                sub.con_amp2TranAligned = makeAlignedCurve(sub.hw->con_amp2Tran, sb.stepMode, AxisScale::Linear, sub.freqPoints_Hz);
            if (sub.hw->con_tran2MonPM)
                sub.con_tran2MonPMAligned = makeAlignedCurve(sub.hw->con_tran2MonPM, sb.stepMode, AxisScale::Linear, sub.freqPoints_Hz);
        }

        // 推入暂存
        subranges.push_back(std::move(sub));
    }

    //替代法校准表数据校验
    if (tpl.stage == TestProcessStage::Testing && tpl.levelMode == LevelModeType::SubstitutionMethod) {
        if (!validateCalibrationData(planLevelCalTable, calFreqs))
            return Exec::TestPlanPtr();
    }

    //如果一个都没构建成功，返回空
    if (subranges.isEmpty()) {
        qWarning() << "No valid subranges to build.";
        return Exec::TestPlanPtr();
    }

    //写回计划子区间列表
    planWritable->subranges = std::move(subranges);

    //设置 flowKind = 硬件模板类型（由一致性校验得到）。无硬件情况返回默认 0。
    planWritable->flowKind = (commonHwType == -1) ? 0 : commonHwType;

    Exec::TestPlanPtr planConst = planWritable;
    return planConst;
}

// 解析硬件模板：先“可写”组装 Exec::Hardware，再“冻结”为 const 指针缓存返回
Exec::HardwarePtr TestPlanBuilder::resolveHardware(int hardwareTemplateId)
{
    // 缓存命中
    if (hwCache_.contains(hardwareTemplateId))
        return hwCache_.value(hardwareTemplateId);

    // 加载可编辑层硬件模板
    HardwareTemplatePtr hwEditable = DataManager::instance()->getFullHardwareTemplate(hardwareTemplateId);
    if (!hwEditable) {
        qCritical() << "resolveHardware failed, id=" << hardwareTemplateId;
        return Exec::HardwarePtr();
    }

    // 可写 Exec::Hardware
    QSharedPointer<Exec::Hardware> hwWritable = QSharedPointer<Exec::Hardware>::create();
    hwWritable->name = hwEditable->name;
    hwWritable->type = hwEditable->type;
    hwWritable->fmin_Hz = hwEditable->frequencyMin;
    hwWritable->fmax_Hz = hwEditable->frequencyMax;

    // 设备配置：用“拷贝到 const 指针”的方式，保证运行期只读
    if (hwEditable->d_Generator)
        hwWritable->gen = QSharedPointer<const GeneratorConfig>::create(*hwEditable->d_Generator);
    if (hwEditable->d_Amplifier)
        hwWritable->amp = QSharedPointer<const AmplifierConfig>::create(*hwEditable->d_Amplifier);
    if (hwEditable->d_FwdPowerMeter)
        hwWritable->fwdPM = QSharedPointer<const PowerMeterConfig>::create(*hwEditable->d_FwdPowerMeter);
    if (hwEditable->d_RevPowerMeter)
        hwWritable->revPM = QSharedPointer<const PowerMeterConfig>::create(*hwEditable->d_RevPowerMeter);
    if (hwEditable->d_MonPowerMeter)
        hwWritable->monPM = QSharedPointer<const PowerMeterConfig>::create(*hwEditable->d_MonPowerMeter);
    if (hwEditable->d_MonReceiver)
        hwWritable->rec = QSharedPointer<const ReceiverConfig>::create(*hwEditable->d_MonReceiver);

    if (hwEditable->type == HardwareTemplateType::RS) {
        if (hwEditable->d_RadiatesAntenna)
            hwWritable->antTx = QSharedPointer<const AntennaConfig>::create(*hwEditable->d_RadiatesAntenna);
        if (hwEditable->d_ReceivesAntenna)
            hwWritable->antRx = QSharedPointer<const AntennaConfig>::create(*hwEditable->d_ReceivesAntenna);
        if (hwEditable->d_MonFieldProbes)
            hwWritable->fieldProbe = QSharedPointer<const FieldProbesConfig>::create(*hwEditable->d_MonFieldProbes);
    } else {
        if (hwEditable->d_InjectionTransducer)
            hwWritable->inj = QSharedPointer<const CurrentInjectionProbeConfig>::create(*hwEditable->d_InjectionTransducer);
        if (hwEditable->d_MonitoringTransducer)
            hwWritable->mon = QSharedPointer<const CurrentInjectionProbeConfig>::create(*hwEditable->d_MonitoringTransducer);
    }
    if (hwEditable->d_MonSpectrumAnalyzer)
        hwWritable->sa = QSharedPointer<const SpectrumAnalyzerConfig>::create(*hwEditable->d_MonSpectrumAnalyzer);

    if (hwEditable->c_SIG2PA)
        hwWritable->c_sig2pa = QSharedPointer<const ConnectorConfig>::create(*hwEditable->c_SIG2PA);
    if (hwEditable->c_FWD2PM)
        hwWritable->c_fwd2pm = QSharedPointer<const ConnectorConfig>::create(*hwEditable->c_FWD2PM);
    if (hwEditable->c_REV2PM)
        hwWritable->c_rev2pm = QSharedPointer<const ConnectorConfig>::create(*hwEditable->c_REV2PM);
    if (hwEditable->c_PA2Transducers)
        hwWritable->c_pa2tr = QSharedPointer<const ConnectorConfig>::create(*hwEditable->c_PA2Transducers);
    if (hwEditable->c_Transducers2PM)
        hwWritable->c_tr2pm = QSharedPointer<const ConnectorConfig>::create(*hwEditable->c_Transducers2PM);

    // 曲线：放大器耦合/天线因子/探头修正等
    if (hwEditable->d_Amplifier) {
        if (hwEditable->d_Amplifier->CouplerType == 0) {
            hwWritable->ampCouplerFwd = buildCurveFromAtt(AttTableList(), hwEditable->d_Amplifier->CouplerValue, true);
            hwWritable->ampCouplerRev = buildCurveFromAtt(AttTableList(), hwEditable->d_Amplifier->CouplerValue, true);
        } else {
            if (hwEditable->d_Amplifier->CouplerTableFWDTableID > 0) {
                const AttTableList att = DataManager::instance()->getAttTable(hwEditable->d_Amplifier->CouplerTableFWDTableID);
                hwWritable->ampCouplerFwd = buildCurveFromAtt(att);
            } else
                hwWritable->ampCouplerFwd = buildCurveFromAtt(AttTableList(), 0, true);

            if (hwEditable->d_Amplifier->CouplerTableREVTableID > 0) {
                const AttTableList att = DataManager::instance()->getAttTable(hwEditable->d_Amplifier->CouplerTableREVTableID);
                hwWritable->ampCouplerRev = buildCurveFromAtt(att);
            } else
                hwWritable->ampCouplerRev = buildCurveFromAtt(AttTableList(), 0, true);
        }
    }

    if (hwEditable->type == HardwareTemplateType::RS && hwEditable->d_ReceivesAntenna) {
        //HFactorsTableID不存在时，返回一个空的数据
        const TransducerTableList tranH = DataManager::instance()->getTransducerTable(hwEditable->d_ReceivesAntenna->HFactorsTableID);
        hwWritable->antHFactors = buildCurveFromTransducer(tranH);
        const TransducerTableList tranV = DataManager::instance()->getTransducerTable(hwEditable->d_ReceivesAntenna->VFactorsTableID);
        hwWritable->antVFactors = buildCurveFromTransducer(tranV);
    }
    if (hwEditable->type == HardwareTemplateType::RS && hwEditable->d_MonFieldProbes) {
        if (hwEditable->d_MonFieldProbes->CorrectionXYZTableID > 0) {
            const AttTableList att = DataManager::instance()->getAttTable(hwEditable->d_MonFieldProbes->CorrectionXYZTableID);
            hwWritable->probeCorr = buildCurveFromAtt(att);
        } else
            hwWritable->probeCorr = buildCurveFromAtt(AttTableList(), 0, true);
    }
    if (hwEditable->type == HardwareTemplateType::CS && hwEditable->d_MonitoringTransducer) {
        const TransducerTableList tranC = DataManager::instance()->getTransducerTable(hwEditable->d_MonitoringTransducer->TransducerTableID);
        hwWritable->probeFactors = buildCurveFromTransducer(tranC);
    }

    if (hwEditable->c_SIG2PA) {
        if (hwEditable->c_SIG2PA->ValueType == 0) {
            hwWritable->con_gen2Amp = buildCurveFromAtt(AttTableList(), hwEditable->c_SIG2PA->AttValue, true);
        } else {
            if (hwEditable->c_SIG2PA->AttTableID > 0) {
                const AttTableList att = DataManager::instance()->getAttTable(hwEditable->c_SIG2PA->AttTableID);
                hwWritable->con_gen2Amp = buildCurveFromAtt(att);
            } else
                hwWritable->con_gen2Amp = buildCurveFromAtt(AttTableList(), 0, true);
        }
    }
    if (hwEditable->c_FWD2PM) {
        if (hwEditable->c_FWD2PM->ValueType == 0) {
            hwWritable->con_Fwd2Pm = buildCurveFromAtt(AttTableList(), hwEditable->c_FWD2PM->AttValue, true);
        } else {
            if (hwEditable->c_FWD2PM->AttTableID > 0) {
                const AttTableList att = DataManager::instance()->getAttTable(hwEditable->c_FWD2PM->AttTableID);
                hwWritable->con_Fwd2Pm = buildCurveFromAtt(att);
            } else
                hwWritable->con_Fwd2Pm = buildCurveFromAtt(AttTableList(), 0, true);
        }
    }
    if (hwEditable->c_REV2PM) {
        if (hwEditable->c_REV2PM->ValueType == 0) {
            hwWritable->con_Rev2Pm = buildCurveFromAtt(AttTableList(), hwEditable->c_REV2PM->AttValue, true);
        } else {
            if (hwEditable->c_REV2PM->AttTableID > 0) {
                const AttTableList att = DataManager::instance()->getAttTable(hwEditable->c_REV2PM->AttTableID);
                hwWritable->con_Rev2Pm = buildCurveFromAtt(att);
            } else
                hwWritable->con_Rev2Pm = buildCurveFromAtt(AttTableList(), 0, true);
        }
    }
    if (hwEditable->c_PA2Transducers) {
        if (hwEditable->c_PA2Transducers->ValueType == 0) {
            hwWritable->con_amp2Tran = buildCurveFromAtt(AttTableList(), hwEditable->c_PA2Transducers->AttValue, true);
        } else {
            if (hwEditable->c_PA2Transducers->AttTableID > 0) {
                const AttTableList att = DataManager::instance()->getAttTable(hwEditable->c_PA2Transducers->AttTableID);
                hwWritable->con_amp2Tran = buildCurveFromAtt(att);
            } else
                hwWritable->con_amp2Tran = buildCurveFromAtt(AttTableList(), 0, true);
        }
    }
    if (hwEditable->c_Transducers2PM) {
        if (hwEditable->c_Transducers2PM->ValueType == 0) {
            hwWritable->con_tran2MonPM = buildCurveFromAtt(AttTableList(), hwEditable->c_Transducers2PM->AttValue, true);
        } else {
            if (hwEditable->c_Transducers2PM->AttTableID > 0) {
                const AttTableList att = DataManager::instance()->getAttTable(hwEditable->c_Transducers2PM->AttTableID);
                hwWritable->con_tran2MonPM = buildCurveFromAtt(att);
            } else
                hwWritable->con_tran2MonPM = buildCurveFromAtt(AttTableList(), 0, true);
        }
    }

    // 冻结成只读 & 缓存
    Exec::HardwarePtr hwConst = hwWritable;
    hwCache_.insert(hardwareTemplateId, hwConst);
    return hwConst;
}

// Att 衰减表 -> 曲线（x: Hz, y: dB）
Exec::CurvePtr TestPlanBuilder::buildCurveFromAtt(const AttTableList &src, double val, bool isConst)
{
    QSharedPointer<Exec::Curve> curveWritable = QSharedPointer<Exec::Curve>::create();
    if (isConst) {
        curveWritable->xScale = AxisScale::Linear;
        curveWritable->yScale = AxisScale::Linear;
        curveWritable->xs_Hz.push_back(1);
        curveWritable->xs_Hz.push_back(2);
        curveWritable->ys.push_back(val);
        curveWritable->ys.push_back(val);
    } else {
        curveWritable->xScale = src.xAxisScale;
        curveWritable->yScale = src.yAxisScale;
        curveWritable->xs_Hz.reserve(src.attList.size());
        curveWritable->ys.reserve(src.attList.size());
        for (const auto &p : src.attList) {
            curveWritable->xs_Hz.push_back(p.Freq); // 确保单位为 Hz（如为 MHz，请 * 1e6）
            curveWritable->ys.push_back(p.Att);
        }
    }
    Exec::CurvePtr curveConst = curveWritable;
    return curveConst;
}

// Transducer 因子表 -> 曲线（x: Hz, y: 因子）
Exec::CurvePtr TestPlanBuilder::buildCurveFromTransducer(const TransducerTableList &src)
{
    QSharedPointer<Exec::Curve> curveWritable = QSharedPointer<Exec::Curve>::create();
    if (src.factorsList.isEmpty()) {
        Exec::CurvePtr curveConst = curveWritable;
        return curveConst;
    } else {
        curveWritable->xScale = src.xAxisScale;
        curveWritable->yScale = src.yAxisScale;
        curveWritable->sourceUnit = src.sourceUnit;
        curveWritable->targetUnit = src.targetUnit;
        curveWritable->xs_Hz.reserve(src.factorsList.size());
        curveWritable->ys.reserve(src.factorsList.size());
        for (const auto &p : src.factorsList) {
            curveWritable->xs_Hz.push_back(p.Freq); // Hz
            curveWritable->ys.push_back(p.Factors); // 因子
        }
    }
    Exec::CurvePtr curveConst = curveWritable;
    return curveConst;
}

// Limit 限值表 -> 曲线（x: Hz, y: 限值，单位与 plan->immunityUnit 一致）
/**
 * @brief TestPlanBuilder::buildCurveFromLimit
 * @param src
 * @param val 固定值
 * @param isConst  true：固定值， false:限值表
 * @param offset CS闭环法测试，添加功率补偿后，将目标限值进行平移，使用补偿后的限值为目标限值
 * @return
 */
Exec::CurvePtr TestPlanBuilder::buildCurveFromLimit(const LimitLineList &src, const double offset, double val, bool isConst)
{
    QSharedPointer<Exec::Curve> curveWritable = QSharedPointer<Exec::Curve>::create();
    if (isConst) {
        curveWritable->xScale = AxisScale::Linear;
        curveWritable->yScale = AxisScale::Linear;
        curveWritable->xs_Hz.push_back(1);
        curveWritable->xs_Hz.push_back(2);
        curveWritable->ys.push_back(val + offset);
        curveWritable->ys.push_back(val + offset);
    } else {
        curveWritable->xScale = src.xAxisScale;
        curveWritable->yScale = src.yAxisScale;
        curveWritable->xs_Hz.reserve(src.limitList.size());
        curveWritable->ys.reserve(src.limitList.size());
        for (const auto &p : src.limitList) {
            curveWritable->xs_Hz.push_back(p.Freq);        // Hz
            curveWritable->ys.push_back(p.Limit + offset); // 限值
        }
    }
    Exec::CurvePtr curveConst = curveWritable;
    return curveConst;
}

// 解析校准表（可把单位统一到内部标准，示例直接拷贝）
Exec::CalTablePtr TestPlanBuilder::resolveCalTable(int calMetaId)
{
    if (calMetaId <= 0)
        return Exec::CalTablePtr();

    if (calCache_.contains(calMetaId))
        return calCache_.value(calMetaId);

    const QList<CalTableConfig> rows = DataManager::instance()->getCalibrationTable(calMetaId);
    QSharedPointer<Exec::CalTable> calWritable = QSharedPointer<Exec::CalTable>::create();
    calWritable->reserve(rows.size());
    for (const auto &c : rows) {
        Exec::CalPoint p;
        p.freq_Hz = c.Freq;                // Hz
        p.amplitude_dBm = c.Amplitude;     // dBm
        p.fwd_dBm = c.FwdPower;            // dBm
        p.rev_dBm = c.RevPower;            // dBm
        p.immunityLevel = c.ImmunityLevel; // V/m 或其它单位
        p.limit = c.LimitImmunityLevel;
        p.swr = c.swr;
        p.loss_dB = c.Loss;
        p.closeLoop = c.CloseLoop;
        p.info = c.info;
        p.immunityUnit = c.ImmunityLevelUnit;
        calWritable->push_back(p);
    }
    Exec::CalTablePtr calConst = calWritable;
    calCache_.insert(calMetaId, calConst);
    return calConst;
}

// 展开频点（Hz）
QVector<double> TestPlanBuilder::expandFreqs(const TestSubBand &sb,
                                             const QVector<FreqTableConfig> *freqTbl)
{
    QVector<double> out;
    switch (sb.freqPlan) {
    case FrequencyPlanType::SweepLinear: {
        if (sb.startFreq <= 0 || sb.stepSize <= 0 || sb.stopFreq <= sb.startFreq) {
            qCritical() << "stepSize <= 0 || stopFreq <= startFreq";
            return out;
        }
        const double start = sb.startFreq;
        const double stop = sb.stopFreq;
        const double step = sb.stepSize;
        double f = start;
        out.push_back(f);
        // while (f + step < stop) {
        //     f += step;
        //     out.push_back(f);
        // }
        // if (out.back() != stop)
        //     out.push_back(stop);

        // 根据模式选择不同的循环逻辑来生成中间点
        if (sb.stepMode == AxisScale::Linear) {
            while (f + step < stop) {
                f += step;
                out.push_back(f);
            }
        } else {
            while (true) {
                double next_f = f * (1.0 + step / 100.0);
                if (next_f > f + 1e-9 && next_f < stop) {
                    f = next_f;
                    out.push_back(f);
                } else
                    break;
            }
        }

        // 检查最后一个元素是否已经是终点（考虑浮点数误差）
        if (std::abs(out.back() - stop) > 1e-9)
            out.push_back(stop);
        break;
    }
    case FrequencyPlanType::FreqTableOnly: {
        if (!freqTbl) {
            qCritical() << "freqTbl is null";
            return out;
        }
        out.clear();
        for (const auto &r : *freqTbl)
            if (r.Freq >= sb.startFreq && r.Freq <= sb.stopFreq)
                out.push_back(r.Freq); // 假定为 Hz
        break;
    }
    case FrequencyPlanType::FreqTablePlusStep: {
        if (!freqTbl || sb.stepSize <= 0) {
            qCritical() << "freqTbl is null || stepSize <= 0";
            return out;
        }
        if (sb.stopFreq <= sb.startFreq) {
            qCritical() << "stopFreq <= startFreq";
            return out;
        }

        const double start = sb.startFreq;
        const double stop = sb.stopFreq;
        const double step = sb.stepSize;
        double f = start;
        out.push_back(f);
        if (sb.stepMode == AxisScale::Linear) {
            while (f + step < stop) {
                f += step;
                out.push_back(f);
            }
        } else {
            while (true) {
                double next_f = f * (1.0 + step / 100.0);
                if (next_f > f + 1e-9 && next_f < stop) {
                    f = next_f;
                    out.push_back(f);
                } else
                    break;
            }
        }

        // 检查最后一个元素是否已经是终点（考虑浮点数误差）
        if (std::abs(out.back() - stop) > 1e-9)
            out.push_back(stop);

        // 将 freqTbl 中的频率点收集到一个集合中，用于快速查找和去重
        QSet<double> anchorPoints;
        for (const auto &r : *freqTbl)
            if (r.Freq >= sb.startFreq && r.Freq <= sb.stopFreq)
                anchorPoints.insert(r.Freq);

        // 将 anchorPoints 添加到 out 中
        for (double anchorFreq : anchorPoints) {
            out.push_back(anchorFreq);
        }
        // 排序
        std::sort(out.begin(), out.end());
        // 去重 (std::unique 要求先排序)
        auto last = std::unique(out.begin(), out.end());
        out.erase(last, out.end());
        break;
    }
    }
    return out;
}

bool TestPlanBuilder::validateCalibrationData(const Exec::CalTablePtr &calTabl, const QVector<double> &calFreqs)
{
    if (!calTabl) {
        qCritical() << " cal Table is null";
        return false;
    }
    if (calTabl->size() != calFreqs.size()) {
        qCritical() << "Size of calTabl and calFreqs are different, calTable.size:" << calTabl->size() << " ,freq.size:" << calFreqs.size();
        return false;
    }

    for (int i = 0; i < calFreqs.size(); ++i) {
        if (!qFuzzyCompare(((*calTabl)[i].freq_Hz + 1.0), (calFreqs[i]) + 1.0)) {
            qCritical() << "Frequency mismatch at index" << i
                        << ", planLevelCalTable frequency:" << (*calTabl)[i].freq_Hz
                        << ", calFreqs frequency:" << calFreqs[i];
            return false;
        }
    }

    return true;
}
